home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: Joystick.cpp
- //
- // Desc: Demonstrates an application which receives immediate
- // joystick data in exclusive mode via a dialog timer.
- //
- // Copyright (c) 1998-2000 Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- #define STRICT
- #include <windows.h>
- #include <basetsd.h>
- #include <dinput.h>
- #include "resource.h"
-
-
-
-
- //-----------------------------------------------------------------------------
- // Function-prototypes
- //-----------------------------------------------------------------------------
- INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
- BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext );
- BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext );
- HRESULT InitDirectInput( HWND hDlg );
- VOID FreeDirectInput();
- HRESULT UpdateInputState( HWND hDlg );
-
-
-
-
- //-----------------------------------------------------------------------------
- // Defines, constants, and global variables
- //-----------------------------------------------------------------------------
- #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
- #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
-
- LPDIRECTINPUT8 g_pDI = NULL;
- LPDIRECTINPUTDEVICE8 g_pJoystick = NULL;
- DIDEVCAPS g_diDevCaps;
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: WinMain()
- // Desc: Entry point for the application. Since we use a simple dialog for
- // user interaction we don't need to pump messages.
- //-----------------------------------------------------------------------------
- int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
- {
- // Display the main dialog box.
- DialogBox( hInst, MAKEINTRESOURCE(IDD_JOYST_IMM), NULL, MainDlgProc );
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: MainDialogProc
- // Desc: Handles dialog messages
- //-----------------------------------------------------------------------------
- INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- switch( msg )
- {
- case WM_INITDIALOG:
- if( FAILED( InitDirectInput( hDlg ) ) )
- {
- MessageBox( NULL, "Error Initializing DirectInput",
- "DirectInput Sample", MB_ICONERROR | MB_OK );
- EndDialog( hDlg, 0 );
- }
-
- // Set a timer to go off 30 times a second. At every timer message
- // the input device will be read
- SetTimer( hDlg, 0, 1000 / 30, NULL );
- return TRUE;
-
- case WM_ACTIVATE:
- if( WA_INACTIVE != wParam && g_pJoystick )
- {
- // Make sure the device is acquired, if we are gaining focus.
- g_pJoystick->Acquire();
- }
- return TRUE;
-
- case WM_TIMER:
- // Update the input device every timer message
- if( FAILED( UpdateInputState( hDlg ) ) )
- {
- KillTimer( hDlg, 0 );
- MessageBox( NULL, "Error Reading Input State. "
- "The sample will now exit.", "DirectInput Sample",
- MB_ICONERROR | MB_OK );
- EndDialog( hDlg, TRUE );
- }
- return TRUE;
-
- case WM_COMMAND:
- switch( LOWORD(wParam) )
- {
- case IDCANCEL:
- KillTimer( hDlg, 0 );
- FreeDirectInput();
- EndDialog( hDlg, 0 );
- return TRUE;
- }
- }
-
- return FALSE; // Message not handled
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitDirectInput()
- // Desc: Initialize the DirectInput variables.
- //-----------------------------------------------------------------------------
- HRESULT InitDirectInput( HWND hDlg )
- {
- HRESULT hr;
-
- // Register with the DirectInput subsystem and get a pointer
- // to a IDirectInput interface we can use.
- // Create a DInput object
- if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
- IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
- return hr;
-
- // Look for a simple joystick we can use for this sample program.
- if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
- EnumJoysticksCallback,
- NULL, DIEDFL_ATTACHEDONLY ) ) )
- return hr;
-
- // Make sure we got a joystick
- if( NULL == g_pJoystick )
- {
- MessageBox( NULL, "Joystick not found. The sample will now exit.",
- "DirectInput Sample",
- MB_ICONERROR | MB_OK );
- EndDialog( hDlg, 0 );
- return S_OK;
- }
-
- // Set the data format to "simple joystick" - a predefined data format
- //
- // A data format specifies which controls on a device we are interested in,
- // and how they should be reported. This tells DInput that we will be
- // passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState().
- if( FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick2 ) ) )
- return hr;
-
- // Set the cooperative level to let DInput know how this device should
- // interact with the system and with other DInput applications.
- if( FAILED( hr = g_pJoystick->SetCooperativeLevel( hDlg, DISCL_EXCLUSIVE |
- DISCL_FOREGROUND ) ) )
- return hr;
-
- // Determine how many axis the joystick has (so we don't error out setting
- // properties for unavailable axis)
- g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
- if ( FAILED( hr = g_pJoystick->GetCapabilities(&g_diDevCaps) ) )
- return hr;
-
- // Enumerate the axes of the joyctick and set the range of each axis. Note:
- // we could just use the defaults, but we're just trying to show an example
- // of enumerating device objects (axes, buttons, etc.).
- if ( FAILED( hr = g_pJoystick->EnumObjects( EnumAxesCallback,
- (VOID*)hDlg, DIDFT_AXIS ) ) )
- return hr;
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: EnumJoysticksCallback()
- // Desc: Called once for each enumerated joystick. If we find one, create a
- // device interface on it so we can play with it.
- //-----------------------------------------------------------------------------
- BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
- VOID* pContext )
- {
- HRESULT hr;
-
- // Obtain an interface to the enumerated joystick.
- hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL );
-
- // If it failed, then we can't use this joystick. (Maybe the user unplugged
- // it while we were in the middle of enumerating it.)
- if( FAILED(hr) )
- return DIENUM_CONTINUE;
-
- // Stop enumeration. Note: we're just taking the first joystick we get. You
- // could store all the enumerated joysticks and let the user pick.
- return DIENUM_STOP;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: EnumAxesCallback()
- // Desc: Callback function for enumerating the axes on a joystick
- //-----------------------------------------------------------------------------
- BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
- VOID* pContext )
- {
- HWND hDlg = (HWND)pContext;
-
- DIPROPRANGE diprg;
- diprg.diph.dwSize = sizeof(DIPROPRANGE);
- diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- diprg.diph.dwHow = DIPH_BYID;
- diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis
- diprg.lMin = -1000;
- diprg.lMax = +1000;
-
- // Set the range for the axis
- if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
- return DIENUM_STOP;
-
- // Set the UI to reflect what axes the joystick supports
- if (pdidoi->guidType == GUID_XAxis)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_X_AXIS ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_X_AXIS_TEXT ), TRUE );
- }
- if (pdidoi->guidType == GUID_YAxis)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_Y_AXIS ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_Y_AXIS_TEXT ), TRUE );
- }
- if (pdidoi->guidType == GUID_ZAxis)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_Z_AXIS ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_Z_AXIS_TEXT ), TRUE );
- }
- if (pdidoi->guidType == GUID_RxAxis)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_X_ROT ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_X_ROT_TEXT ), TRUE );
- }
- if (pdidoi->guidType == GUID_RyAxis)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_Y_ROT ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_Y_ROT_TEXT ), TRUE );
- }
- if (pdidoi->guidType == GUID_RzAxis)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_Z_ROT ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_Z_ROT_TEXT ), TRUE );
- }
- if (pdidoi->guidType == GUID_Slider)
- {
- EnableWindow( GetDlgItem( hDlg, IDC_SLIDER0 ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_SLIDER0_TEXT ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_SLIDER1 ), TRUE );
- EnableWindow( GetDlgItem( hDlg, IDC_SLIDER1_TEXT ), TRUE );
- }
-
- return DIENUM_CONTINUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateInputState()
- // Desc: Get the input device's state and display it.
- //-----------------------------------------------------------------------------
- HRESULT UpdateInputState( HWND hDlg )
- {
- HRESULT hr;
- CHAR strText[128]; // Device state text
- DIJOYSTATE2 js; // DInput joystick state
- CHAR* str;
-
- if( NULL == g_pJoystick )
- return S_OK;
-
- // Poll the device to read the current state
- hr = g_pJoystick->Poll();
- if( FAILED(hr) )
- {
- // DInput is telling us that the input stream has been
- // interrupted. We aren't tracking any state between polls, so
- // we don't have any special reset that needs to be done. We
- // just re-acquire and try again.
- hr = g_pJoystick->Acquire();
- while( hr == DIERR_INPUTLOST )
- hr = g_pJoystick->Acquire();
-
- // hr may be DIERR_OTHERAPPHASPRIO or other errors. This
- // may occur when the app is minimized or in the process of
- // switching, so just try again later
- return S_OK;
- }
-
- // Get the input's device state
- if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js ) ) )
- return hr; // The device should have been acquired during the Poll()
-
- // Display joystick state to dialog
- wsprintf( strText, "%ld", js.lX );
- SetWindowText( GetDlgItem( hDlg, IDC_X_AXIS ), strText );
- wsprintf( strText, "%ld", js.lY );
- SetWindowText( GetDlgItem( hDlg, IDC_Y_AXIS ), strText );
- wsprintf( strText, "%ld", js.lZ );
- SetWindowText( GetDlgItem( hDlg, IDC_Z_AXIS ), strText );
-
- // For steering wheels
- wsprintf( strText, "%ld", js.lRx );
- SetWindowText( GetDlgItem( hDlg, IDC_X_ROT ), strText );
- wsprintf( strText, "%ld", js.lRy );
- SetWindowText( GetDlgItem( hDlg, IDC_Y_ROT ), strText );
- wsprintf( strText, "%ld", js.lRz );
- SetWindowText( GetDlgItem( hDlg, IDC_Z_ROT ), strText );
-
- // For slider controls
- wsprintf( strText, "%ld", js.rglSlider[0] );
- SetWindowText( GetDlgItem( hDlg, IDC_SLIDER0 ), strText );
- wsprintf( strText, "%ld", js.rglSlider[1] );
- SetWindowText( GetDlgItem( hDlg, IDC_SLIDER1 ), strText );
-
- // Point of view
- if( g_diDevCaps.dwPOVs >= 1 )
- {
- wsprintf( strText, "%ld", js.rgdwPOV[0] );
- SetWindowText( GetDlgItem( hDlg, IDC_POV ), strText );
- }
-
- // Fill up text with which buttons are pressed
- str = strText;
- for( int i = 0; i < 128; i++ )
- {
- if ( js.rgbButtons[i] & 0x80 )
- str += wsprintf( str, "%02d ", i );
- }
- *str = 0; // Terminate the string
-
- SetWindowText( GetDlgItem( hDlg, IDC_BUTTONS ), strText );
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: FreeDirectInput()
- // Desc: Initialize the DirectInput variables.
- //-----------------------------------------------------------------------------
- VOID FreeDirectInput()
- {
- // Unacquire the device one last time just in case
- // the app tried to exit while the device is still acquired.
- if( g_pJoystick )
- g_pJoystick->Unacquire();
-
- // Release any DirectInput objects.
- SAFE_RELEASE( g_pJoystick );
- SAFE_RELEASE( g_pDI );
- }
-
-
-
-